/*
 * $Id: $
 * 
 * Copyright (c) 2001-2008 Accentrix Company Limited. All Rights Reserved.
 * 
 * Accentrix Company Limited. ("Accentrix") retains copyright on all text, source
 * and binary code contained in this software and documentation. Accentrix grants
 * Licensee a limited license to use this software, provided that this copyright
 * notice and license appear on all copies of the software. The software source
 * code is provided for reference purposes only and may not be copied, modified 
 * or distributed.
 * 
 * THIS SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS," WITHOUT ANY WARRANTY OF
 * ANY KIND UNLESS A SEPARATE WARRANTIES IS PURCHASED FROM ACCENTRIX AND REMAINS
 * VALID.  ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. ACCENTRIX SHALL NOT BE LIABLE
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING OR MODIFYING THE
 * SOFTWARE OR ITS DERIVATIVES.
 * 
 * IN NO EVENT WILL ACCENTRIX BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
 * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
 * HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE
 * USE OF OR INABILITY TO USE SOFTWARE, EVEN IF ACCENTRIX HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */
package com.lightsaber.trade.cloth.web.programme;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang.xwork.StringUtils;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springside.modules.utils.web.struts2.Struts2Utils;

import com.lightsaber.trade.core.entity.AuditedObject;
import com.lightsaber.trade.core.entity.BaseEntity;
import com.lightsaber.trade.core.web.BaseAction;
import com.lightsaber.trade.cloth.entity.programme.LaunchVersion;
import com.lightsaber.trade.cloth.entity.programme.OfferingCampus;
import com.lightsaber.trade.cloth.entity.programme.Programme;
import com.lightsaber.trade.cloth.entity.programme.ProgrammeStatus;
import com.lightsaber.trade.cloth.entity.programme.Stream;
import com.lightsaber.trade.cloth.service.param.ParamService;
import com.lightsaber.trade.cloth.service.programme.ProgrammeManager;
import com.lightsaber.trade.cloth.service.programme.StreamManager;

@Namespace("/programme")
@Result(name = "DELETE-SECCUSS", location = "programme.action", type = "redirect")
public class ProgrammeInfoAction extends BaseAction {
    private static final long serialVersionUID = 4118497987743384976L;

    private static final Logger log = LoggerFactory.getLogger(ProgrammeInfoAction.class);
    @Autowired
    private transient ProgrammeManager programmeManager;
    @Autowired
    private transient ParamService paramService;
    @Autowired
    private StreamManager streamManager;

    private Programme programme;
    private String programmeId;
    private String streamId;

    // --------- CHECK CODE-----------
    private String code;
    private String launchYear;
    private String launchVersion;
    // --------- CHECK CODE-----------

    private List<Stream> streams;

    private String discipline_label;

    private String qfLevel_label;

    private Object studyMode_label;

    private String fundingMode_label;

    // ****************** copy or revise**********************
    private String copyFromId;
    private String canEditCode;

    private boolean isFeederOrReceiver;

    private String revisionType_label;

    private boolean canEdit;

    @Override
    public String execute() throws Exception {
        return list();
    }

    public String list() {
        if (StringUtils.isNotBlank(programmeId)) {
            programme = programmeManager.get(programmeId);
            canEdit = programme.getStatus() == null ? true : programme.getStatus().isCanEdit();
            discipline_label = paramService.getDisciplineLabel(programme.getDiscipline());
            qfLevel_label = paramService.getQFLevelLabel(programme.getQfLevel());
            studyMode_label = paramService.getStudyModeLabel(programme.getStudyMode());
            fundingMode_label = paramService.getFundingModeLabel(programme.getFundingMode());

            revisionType_label = paramService.getRevisionTypeLabel(programme.getRevisionType());

            isFeederOrReceiver = programmeManager.isFeederOrReceiver(programme.getCode());

            streams = streamManager.findByProgrammeId(programmeId);
        } else {
            canEdit = true;
        }

        return SUCCESS;
    }

    public void validateSave() throws Exception {

        if (StringUtils.isBlank(programmeId)) {

            // 1. validate code year and version
            if (programmeManager.hasSameCodeAndLaunchYearAndLaunchVersion(programme)) {
                addActionError("There is programme has same code, launch year and launch version existed, please enter new value and try again.");
            }

            // 2. validate version
            try {
                LaunchVersion.valueOf(programme.getLaunchVersion());
            } catch (Exception e) {
                this.addActionError("Launch Version must input like: "
                        + "M01, M02, M03, M04, M05, M06, M07, M08, M09, M10, M11, M12, Spr, Sum, Aut, Win");
            }

            if (this.hasActionErrors()) {
                discipline_label = paramService.getDisciplineLabel(programme.getDiscipline());
                qfLevel_label = paramService.getQFLevelLabel(programme.getQfLevel());
                studyMode_label = paramService.getStudyModeLabel(programme.getStudyMode());
                fundingMode_label = paramService.getFundingModeLabel(programme.getFundingMode());

                canEdit = true;
            }
        }

    }

    public String copy() throws Exception {
        Programme programmeDB = programmeManager.get(copyFromId);

        programme = new Programme();
        BeanUtils
                .copyProperties(programmeDB, programme, new String[] { BaseEntity.ID,
                        BaseEntity.VERSION, AuditedObject.CREATED_BY, AuditedObject.CREATED_DATE,
                        "status" });

        discipline_label = paramService.getDisciplineLabel(programme.getDiscipline());
        qfLevel_label = paramService.getQFLevelLabel(programme.getQfLevel());
        studyMode_label = paramService.getStudyModeLabel(programme.getStudyMode());
        fundingMode_label = paramService.getFundingModeLabel(programme.getFundingMode());

        revisionType_label = paramService.getRevisionTypeLabel(programme.getRevisionType());

        canEdit = null == programme.getStatus() ? true : programme.getStatus().isCanEdit();
        return INPUT;
    }

    public String save() throws Exception {

        if (StringUtils.isBlank(copyFromId)) {
            programmeManager.save(programme);
            programmeId = programme.getId();// Display the programmeId on page

        } else {

            programmeManager.saveCopy(programme, copyFromId);
            programmeId = programme.getId();// Display the programmeId on page
            copyFromId = null;
            canEditCode = null;
        }

        addActionMessage(getText(PROCESSED_SUCCESS));

        return list();
    }

    public void validateDelete() {
        // if
        // (programmeManager.programmePlanningItemExistsCode(programme.getCode()))
        // {
        // this.addActionError("Level 2 has assoiated this Programme, can't be deleted.");
        // }
    }

    public String delete() throws Exception {
        programmeManager.delete(programmeId);

        addActionMessage(getText(PROCESSED_SUCCESS));
        return "DELETE-SECCUSS";
    }

    public String deleteStream() throws Exception {
        streamManager.delete(streamId);

        addActionMessage(getText(PROCESSED_SUCCESS));

        return list();
    }

    public void checkCode() {
        Map<String, String> reMap = programmeManager.checkCode(code, launchYear, launchVersion);
        Struts2Utils.renderJson(reMap);
    }

    public void validateConfirm() {
        programme = programmeManager.get(programme.getId());
        List<OfferingCampus> offeringCampusList = programme.getOfferingCampusList();
        if (offeringCampusList.size() == 0) {
            this.addActionError("At least one of Offering Campus of this Programme.");
        }
        /*
         * List<CurriculumHour> curriculumHourList =
         * programme.getCurriculumHours(); for (CurriculumHour curriculumHour :
         * curriculumHourList) { if (curriculumHour.getHours() == null) {
         * this.addActionError
         * ("Curriculum Hour of this Programme must be input."); break; } }
         */
        if (this.hasActionErrors()) {
            list();// prepare page parametes
        }
    }

    public String confirm() {
        if (null != programmeId && !"".equals(programmeId)) {
            Programme oldP = programmeManager.get(programmeId);

            if (null == oldP) {
                addActionMessage("programme confirm  failed, no programme found!");
                return "info";
            }
            if (oldP.getStatus() == ProgrammeStatus.Confirmed) {
                addActionMessage("programme " + oldP.getCode()
                        + " confirm  failed, because it was already comfirmed before!");
                return "info";
            }
            try {
                Map<String, String> exMap = programmeManager.confirm(oldP);
                if (exMap.isEmpty()) {
                    addActionMessage("programme " + oldP.getCode() + " confirm success!");
                } else {
                    addActionMessage("programme " + oldP.getCode() + " confirm  failed due to "
                            + exMap.get("info"));
                }

            } catch (Exception e) {
                log.error(e.getMessage(), e);
                addActionMessage("programme " + oldP.getCode()
                        + " confirm  failed due to incomplete data");
            }
        }
        return list();
    }

    public Programme getProgramme() {
        return programme;
    }

    public void setProgramme(final Programme programme) {
        this.programme = programme;
    }

    public String getProgrammeId() {
        return programmeId;
    }

    public void setProgrammeId(final String programmeId) {
        this.programmeId = programmeId;
    }

    public ParamService getParamService() {
        return paramService;
    }

    public void setParamService(final ParamService paramService) {
        this.paramService = paramService;
    }

    public List<Stream> getStreams() {
        return streams;
    }

    public void setStreams(final List<Stream> streams) {
        this.streams = streams;
    }

    public String getStreamId() {
        return streamId;
    }

    public String getLaunchYear() {
        return launchYear;
    }

    public void setLaunchYear(String launchYear) {
        this.launchYear = launchYear;
    }

    public String getLaunchVersion() {
        return launchVersion;
    }

    public void setLaunchVersion(String launchVersion) {
        this.launchVersion = launchVersion;
    }

    public void setStreamId(final String streamId) {
        this.streamId = streamId;
    }

    public String getCode() {
        return code;
    }

    public void setCode(final String code) {
        this.code = code;
    }

    public String getDiscipline_label() {
        return discipline_label;
    }

    public void setDiscipline_label(String discipline_label) {
        this.discipline_label = discipline_label;
    }

    public String getQfLevel_label() {
        return qfLevel_label;
    }

    public void setQfLevel_label(String qfLevel_label) {
        this.qfLevel_label = qfLevel_label;
    }

    public Object getStudyMode_label() {
        return studyMode_label;
    }

    public void setStudyMode_label(Object studyMode_label) {
        this.studyMode_label = studyMode_label;
    }

    public String getFundingMode_label() {
        return fundingMode_label;
    }

    public String getCopyFromId() {
        return copyFromId;
    }

    public String getRevisionType_label() {
        return revisionType_label;
    }

    public void setRevisionType_label(String revisionType_label) {
        this.revisionType_label = revisionType_label;
    }

    public void setCopyFromId(String copyFromId) {
        this.copyFromId = copyFromId;
    }

    public boolean isFeederOrReceiver() {
        return isFeederOrReceiver;
    }

    public void setFeederOrReceiver(boolean isFeederOrReceiver) {
        this.isFeederOrReceiver = isFeederOrReceiver;
    }

    public String getCanEditCode() {
        return canEditCode;
    }

    public void setCanEditCode(String canEditCode) {
        this.canEditCode = canEditCode;
    }

    public void setFundingMode_label(String fundingMode_label) {
        this.fundingMode_label = fundingMode_label;
    }

    public boolean isCanEdit() {
        return canEdit;
    }

    public void setCanEdit(boolean canEdit) {
        this.canEdit = canEdit;
    }
}
